package com.css.util;

import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class FileZipUtil {
	
	/**
     * zip文件压缩
     * @param srcDir 待压缩文件夹/文件名
     * @param outZipFile 生成的压缩包名字
     */
    public static void zipCompress(String srcDir, String outZipFile) throws Exception {
        //创建zip输出流
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outZipFile));
        File srcFile = new File(srcDir);
        compress(srcFile, zos, null);
        zos.close();
    }
    
    /**
     * @param name 压缩文件名，可以写为null保持默认
     */
    //递归压缩
    public static void compress(File srcFile, ZipOutputStream zos, String name) throws IOException {
        if (name == null) {
            name = srcFile.getName();
        }
        if(srcFile.isFile()){
        	//压缩文件情况
        	zos.putNextEntry(new ZipEntry(name));
            FileInputStream fis = new FileInputStream(srcFile);
            BufferedInputStream bis = new BufferedInputStream(fis);
            int len=-1;
            //将源文件写入到zip文件中
            byte[] buf = new byte[1024];
            while ((len = bis.read(buf)) != -1) {
            	zos.write(buf,0,len);
            }
            zos.closeEntry();
            bis.close();
            fis.close();
        }else{
        	//压缩文件夹情况
        	 File[] flist = srcFile.listFiles();
             if (flist == null || flist.length == 0){
            	//如果文件夹为空，则只需在目的地zip文件中写入一个目录进入
             	zos.putNextEntry(new ZipEntry(name + "/"));
             	zos.closeEntry();
             } else{
            	//如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
                 for (int i = 0; i < flist.length; i++) {
                     compress(flist[i], zos, name + "/" + flist[i].getName());
                 }
             }
        }
    }

    /**
     * zip解压
     * @param zipFilePath 待解压文件名
     * @param destDirPath  解压路径
     */
    public static void zipUncompress(String zipFilePath,String destDirPath) throws Exception {
        File srcFile = new File(zipFilePath);//获取当前压缩文件
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new Exception(srcFile.getPath() + "所指文件不存在");
        }
        //开始解压
        //构建解压输入流
        ZipInputStream zis = new ZipInputStream(new FileInputStream(srcFile));
        ZipEntry entry = null;
        File file = null;
        while ((entry = zis.getNextEntry()) != null) {
            if (!entry.isDirectory()) {
                file = new File(destDirPath, entry.getName());
                if (!file.exists()) {
                    new File(file.getParent()).mkdirs();//创建此文件的上级目录
                }
                OutputStream out = new FileOutputStream(file);
                BufferedOutputStream bos = new BufferedOutputStream(out);
                int len = -1;
                byte[] buf = new byte[1024];
                while ((len = zis.read(buf)) != -1) {
                    bos.write(buf, 0, len);
                }
                // 关流顺序，先打开的后关闭
                bos.close();
                out.close();
            }
        }
        zis.close();
    }

    /**
     * 解压缩到指定目录并直接返回压缩包内的文件列表
     * @param srcZipFile 待解压文件名
     * @param destDirPath  解压路径
     * @author  xinyue
     */
    public static File[] zipUncompressAndList(File srcZipFile,String destDirPath) throws Exception {
        try {
        	// 判断源文件是否存在
            if (!srcZipFile.exists()) {
                throw new Exception(srcZipFile.getPath() + "所指文件不存在");
            }
            //开始解压
            //构建解压输入流 (windows环境下，默认字符集为GBK，ZipFile默认使用UTF-8字符集，当文件名存在中文时，处理时就会报错)
            ZipInputStream zis = new ZipInputStream(new FileInputStream(srcZipFile),Charset.forName("GBK"));
            ZipEntry entry = null;
            File file = null;
            String zipFileName = "";
            while ((entry = zis.getNextEntry()) != null) {
            	if(zipFileName == ""){
            		zipFileName = entry.getName().substring(0,entry.getName().indexOf("/"));
            	}
                if (!entry.isDirectory()) {
                    file = new File(destDirPath, entry.getName());
                    if (!file.exists()) {
                        new File(file.getParent()).mkdirs();//创建此文件的上级目录
                    }
                    OutputStream out = new FileOutputStream(file);
                    BufferedOutputStream bos = new BufferedOutputStream(out);
                    int len = -1;
                    byte[] buf = new byte[1024];
                    while ((len = zis.read(buf)) != -1) {
                        bos.write(buf, 0, len);
                    }
                    // 关流顺序，先打开的后关闭
                    bos.close();
                    out.close();
                }
            }
            zis.close();
            //String zipFileName = srcZipFile.getName().substring(0,srcZipFile.getName().lastIndexOf("."));
            File uncompressedFold = new File(destDirPath + "/" + zipFileName);
            if(uncompressedFold.exists()){
          	  return uncompressedFold.listFiles();
            }
		} catch (Exception e) {
			 e.printStackTrace();
		}
        return null;
    }
    
    /**
     *直接获取zip包内数据文件的文件名
     * @param zipFile
     * @return
     */
	public static String getZipInFileName(File zipFile) {
		String fileName = "";
		try {
			ZipEntry zipEntry = null;
			if (zipFile.exists()) {
				ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile), Charset.forName("GBK")); // 解决包内文件存在中文时的中文乱码问题
				while ((zipEntry = zis.getNextEntry()) != null) {
					if (zipEntry.getName().contains("_explain")) {
						continue;
					}
					fileName = zipEntry.getName().substring(zipEntry.getName().lastIndexOf("/") + 1);
					break;
				}
				zis.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return fileName;
	}
	
	/**
	 *【有bug 获取信息后会一直占有该zip包，无法删除】 
     *不解压直接获取zip包内数据文件的文件名及校验码
     * @param zipFile
     * @return
     */
	public static Map<String, String> getZipInFileNameAndUnicode(File zipFile) {
		Map<String,String> map = new HashMap<String,String>();
		try {
			ZipFile zf = new ZipFile(zipFile); 
			ZipEntry zipEntry = null;
			if (zipFile.exists()) {
				ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile), Charset.forName("GBK")); // 解决包内文件存在中文时的中文乱码问题
				while ((zipEntry = zis.getNextEntry()) != null) {
					if (zipEntry.getName().contains("_explain")) {
//					    long size = zipEntry.getSize();
//		                if (size > 0) {
		                    BufferedReader br = new BufferedReader(new InputStreamReader(zf.getInputStream(zipEntry)));
		                    String line;
		                    while ((line = br.readLine()) != null) {
		                    	String[] arrays = line.split("@");
		                    	map.put("fileName", StringHelper.isEmpty(arrays[1])?"":arrays[1]);
		                    	map.put("unicode", StringHelper.isEmpty(arrays[0])?"":arrays[0]);
		                    }
		                    br.close();
		                    break;
//		                }
					}
				}
				zis.closeEntry();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}
    
	/**
	 * 不解压直接获取zip包内数据文件的文件名及校验码
	 * @param zis
	 * @return
	 * @throws IOException
	 */
	public static Map<String, String> getZipInFileNameAndUnicode(ZipInputStream zis) throws IOException {
		ZipEntry zipEntry = null;
		BufferedReader br = null;
		Map<String,String> map = new HashMap<String,String>();
		try {
			while((zipEntry = zis.getNextEntry()) != null){
	        	 if(zipEntry.getName().contains("_explain")){
	        		 br = new BufferedReader(new InputStreamReader(zis));
	        		 String line;
	        		 while((line = br.readLine())!= null){
	        			String[] arrays = line.split("@");
	                    map.put("fileName", StringHelper.isEmpty(arrays[1])?"":arrays[1]);
	                    map.put("unicode", StringHelper.isEmpty(arrays[0])?"":arrays[0]);
	        		 }
	        		 break;
		    	  }
	        }
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(br!=null){
				br.close(); 
			}
		}
		return map;
    }

	
    public static void main(String[] args) {
        try {
			//zipUncompressAndList(new File("C:\\Users\\xinyue\\Desktop\\123\\Importusers.zip"),"C:\\Users\\xinyue\\Desktop\\123");
			//zipUncompress("C:\\Users\\xinyue\\Desktop\\123\\Desktop.zip","C:\\Users\\xinyue\\Desktop\\123");
			//zipCompress("D:\\usr\\local\\cssoa\\webapps\\tempMergeFolds\\zipfile[]", "D:\\usr\\local\\cssoa\\webapps\\sendArea\\zipfile[].zip");
            //foldCompress("D:/usr/local/cssoa/webapps/receiveArea/org.apache.commons.io-2.4-sources/org.apache.commons.io-2.4-sources_explain.txt", "D:/usr/local/cssoa/webapps/receiveArea/org.apache.commons.io-2.4-sources/org.apache.commons.io-2.4-sources_explain.zip");
            
            /*ZipUncompress("D:\\ytt.zip","D:\\ytt的解压文件");*/
            /*File[] files = zipUncompressAndList(new File("D:\\usr\\local\\cssoa\\webapps\\receiveArea\\论文格式.zip"),"D:\\usr\\local\\cssoa\\webapps\\receiveArea");
            for (File file : files) {
				System.out.println(file.getName());
			}*/
//        	System.out.println(getZipInFileName(new File("D:/usr/local/cssoa/webapps/15856440751609310821.zip")));;
        	
        	/*File[] filearray = new File("D:/usr/local/cssoa/webapps/test").listFiles();
        	for (File file : filearray) {
        		ZipInputStream zin = new ZipInputStream(new FileInputStream(file), Charset.forName("GBK")); 
        		Map<String, String> map = getZipInFileNameAndUnicode(zin);
            	System.out.println(map.get("fileName"));
            	System.out.println(map.get("unicode"));
        		//readZipFile("D:/usr/local/cssoa/webapps/test/1587253420703@fea595ad3364979b9c08af8f1da1e615.zip");
        		if(file.exists()){
            		boolean b = file.delete();
            		System.out.println(b + "删除成功！");
            	}
			}*/
        	zipCompress("C:\\Users\\xinyue\\Desktop\\123\\Importusers","C:\\Users\\xinyue\\Desktop\\123\\123.zip");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}